/*
图片处理
*/

package imageclipper

import (
	"errors"
	"fmt"
	"image"
	"image/draw"
	"image/jpeg"
	"log"
	"os"
	"path"

	"github.com/disintegration/imaging"
)

/*
切图 - 源文件路径切图
	params:
		img_path: 图片文件路径
		left:     左坐标
		right:    右坐标
		top:      顶坐标
		bottom:   底坐标
	returns:
		err: error
*/
func cut(img_path string, left, top, right, bottom int) (err error) {
	if (right-left) == 0 || (bottom-top) == 0 {
		if err := os.Remove(img_path); err != nil {
			return err
		}
		return nil
	}
	imga, err := imaging.Open(img_path)
	if err != nil {
		return err
	}
	imgb := imaging.Crop(imga, image.Rect(left, top, right, bottom))
	if err := imaging.Save(imgb, img_path); err != nil {
		return err
	}
	return nil
}

/*
地毯式图片标准化尺寸整理
	1. 列级整理, 按照每个图片 2448 宽度, 重新整理图片
	2. 行级整理, 按照每个图片 2048 高度, 重新整理图片
	params:
		file_path: 文件路径
		extension: 图片扩展名
		new_cols:  目标列数
		new_rows:  目标行数
	returns:
		err: error
*/
func flush(file_path, extension string, new_cols, new_rows int) (err error) {

	cols, rows, err := getSourceRect(file_path, extension)
	if err != nil {
		return err
	}
	log.Println("向上:", cols, rows)

	for r := 0; r < rows; r++ {
		for c := 0; c < (cols - 1); c++ {
			f1 := path.Join(file_path, fmt.Sprintf("%d_%d.%s", c, r, extension))
			f2 := path.Join(file_path, fmt.Sprintf("%d_%d.%s", c+1, r, extension))
			if err := resize(f1, f2); err != nil {
				return err
			}
			// time.Sleep(time.Second)
		}
	}

	cols, rows, err = getSourceRect(file_path, extension)
	if err != nil {
		return err
	}
	log.Println("向左:", cols, rows)

	for c := 0; c < cols; c++ {
		for r := 0; r < (rows - 1); r++ {
			f1 := path.Join(file_path, fmt.Sprintf("%d_%d.%s", c, r, extension))
			f2 := path.Join(file_path, fmt.Sprintf("%d_%d.%s", c, r+1, extension))
			if err := resize(f1, f2); err != nil {
				return err
			}
			// time.Sleep(time.Second)
		}
	}

	return nil
}

/*
图像加载
	1. 图片加载
	params:
		img_path: 图片文件路径
	returns:
		img: 图片对象
		err: error
*/
func loadImage(img_path string) (img image.Image, err error) {
	fi, err := os.Stat(img_path)
	if err != nil {
		return
	}
	if fi.IsDir() {
		err = errors.New("no file")
		return
	}
	fo, err := os.Open(img_path)
	if err != nil {
		return
	}
	defer fo.Close()
	img, err = jpeg.Decode(fo)
	if err != nil {
		return
	}
	return img, nil
}

func saveImage(img_path string, img image.Image) (err error) {
	o1, err := os.Create(img_path)
	if err != nil {
		return err
	}
	defer o1.Close()
	err = jpeg.Encode(o1, img, &jpeg.Options{Quality: 95})
	if err != nil {
		return err
	}
	return nil
}

func resize(f1, f2 string) (err error) {

	log.Println(f1, f2)

	// 第一个文件
	i1, err := loadImage(f1)
	if err != nil {
		return
	}

	// 第二个文件
	i2, err := loadImage(f2)
	if err != nil {
		return err
	}

	y1 := i1.Bounds().Size().Y
	y2 := i2.Bounds().Size().Y
	x1 := i1.Bounds().Size().X
	x2 := i2.Bounds().Size().X

	// 向左合并, 再拆分
	if y1 == y2 && x1 != x2 && (x1+x2) >= tileWidth {

		if x1 == tileWidth && x2 == tileWidth {
			return nil
		}

		rgba := image.NewRGBA(image.Rect(0, 0, (x1 + x2), y1))
		draw.Draw(rgba, rgba.Bounds(), i1, i1.Bounds().Min, draw.Over)
		draw.Draw(rgba, rgba.Bounds(), i2, i2.Bounds().Min.Sub(image.Pt(i1.Bounds().Max.X, 0)), draw.Over)

		sub1 := rgba.SubImage(image.Rect(0, 0, tileWidth, y1))
		if err := saveImage(f1, sub1); err != nil {
			return err
		}

		if ((x1 + x2) - tileWidth) > 0 {
			sub2 := rgba.SubImage(image.Rect(tileWidth, 0, x1+x2, y1))
			if err := saveImage(f2, sub2); err != nil {
				return err
			}
		} else {
			if err := os.Remove(f2); err != nil {
				return err
			}
		}

		return nil
	}

	// 向上合并, 再拆分
	if x1 == x2 && y1 != y2 && (y1+y2) >= tileHeight {

		if y1 == tileHeight && y2 == tileHeight {
			return nil
		}

		rgba := image.NewRGBA(image.Rect(0, 0, x1, y1+y2))
		draw.Draw(rgba, rgba.Bounds(), i1, i1.Bounds().Min, draw.Over)
		draw.Draw(rgba, rgba.Bounds(), i2, i2.Bounds().Min.Sub(image.Pt(0, i1.Bounds().Max.Y)), draw.Over)

		sub1 := rgba.SubImage(image.Rect(0, 0, x1, tileHeight))
		if err := saveImage(f1, sub1); err != nil {
			return err
		}

		if ((y1 + y2) - tileHeight) > 0 {
			sub2 := rgba.SubImage(image.Rect(0, tileHeight, x1, y1+y2))
			if err := saveImage(f2, sub2); err != nil {
				return err
			}
		} else {
			if err := os.Remove(f2); err != nil {
				return err
			}
		}

	}

	return nil
}
